home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / fax / src / faxd / Class20.c++ < prev    next >
C/C++ Source or Header  |  1994-08-01  |  7KB  |  243 lines

  1. /*    $Header: /usr/people/sam/fax/faxd/RCS/Class20.c++,v 1.8 1994/04/25 16:10:06 sam Rel $ */
  2. /*
  3.  * Copyright (c) 1994 Sam Leffler
  4.  * Copyright (c) 1994 Silicon Graphics, Inc.
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and 
  7.  * its documentation for any purpose is hereby granted without fee, provided
  8.  * that (i) the above copyright notices and this permission notice appear in
  9.  * all copies of the software and related documentation, and (ii) the names of
  10.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  11.  * publicity relating to the software without the specific, prior written
  12.  * permission of Sam Leffler and Silicon Graphics.
  13.  * 
  14.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  15.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  16.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  17.  * 
  18.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  19.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  20.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  22.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  23.  * OF THIS SOFTWARE.
  24.  */
  25. #include "Class20.h"
  26. #include "ModemConfig.h"
  27.  
  28. #include <stdlib.h>
  29. #include <ctype.h>
  30.  
  31. Class20Modem::Class20Modem(FaxServer& s, const ModemConfig& c) : Class2Modem(s,c)
  32. {
  33.     serviceType = SERVICE_CLASS20;
  34.     setupDefault(classCmd,    conf.class2Cmd,        "+FCLASS=2.0");
  35.     setupDefault(mfrQueryCmd,    conf.mfrQueryCmd,    "+FMI?");
  36.     setupDefault(modelQueryCmd,    conf.modelQueryCmd,    "+FMM?");
  37.     setupDefault(revQueryCmd,    conf.revQueryCmd,    "+FMR?");
  38.     setupDefault(dccQueryCmd,    conf.class2DCCQueryCmd, "+FCC=?");
  39.     setupDefault(abortCmd,    conf.class2AbortCmd,    "KS");
  40.  
  41.     setupDefault(borCmd,    conf.class2BORCmd,    "BO=0");
  42.     setupDefault(tbcCmd,    conf.class2TBCCmd,    "PP=0");
  43.     setupDefault(crCmd,        conf.class2CRCmd,    "CR=1");
  44.     setupDefault(phctoCmd,    conf.class2PHCTOCmd,    "CT=30");
  45.     setupDefault(bugCmd,    conf.class2BUGCmd,    "BU=1");
  46.     setupDefault(lidCmd,    conf.class2LIDCmd,    "LI");
  47.     setupDefault(dccCmd,    conf.class2DCCCmd,    "CC");
  48.     setupDefault(disCmd,    conf.class2DISCmd,    "IS");
  49.     setupDefault(cigCmd,    conf.class2CIGCmd,    "PI");
  50.     setupDefault(splCmd,    conf.class2SPLCmd,    "SP");
  51.  
  52.     // ignore procedure interrupts
  53.     setupDefault(pieCmd,    conf.class2PIECmd,    "IE=0");
  54.     // enable reporting of everything
  55.     setupDefault(nrCmd,        conf.class2NRCmd,    "NR=1,1,1,1");
  56. }
  57.  
  58. Class20Modem::~Class20Modem()
  59. {
  60. }
  61.  
  62. ATResponse
  63. Class20Modem::atResponse(char* buf, long ms)
  64. {
  65.     if (FaxModem::atResponse(buf, ms) == AT_OTHER &&
  66.       (buf[0] == '+' && buf[1] == 'F')) {
  67.     if (strneq(buf, "+FHS:", 5)) {
  68.         processHangup(buf+5);
  69.         lastResponse = AT_FHNG;
  70.     } else if (strneq(buf, "+FCO", 4))
  71.         lastResponse = AT_FCON;
  72.     else if (strneq(buf, "+FPO", 4))
  73.         lastResponse = AT_FPOLL;
  74.     else if (strneq(buf, "+FVO", 4))
  75.         lastResponse = AT_FVO;
  76.     else if (strneq(buf, "+FIS:", 5))
  77.         lastResponse = AT_FDIS;
  78.     else if (strneq(buf, "+FNF:", 5))
  79.         lastResponse = AT_FNSF;
  80.     else if (strneq(buf, "+FCI:", 5))
  81.         lastResponse = AT_FCSI;
  82.     else if (strneq(buf, "+FPS:", 5))
  83.         lastResponse = AT_FPTS;
  84.     else if (strneq(buf, "+FCS:", 5))
  85.         lastResponse = AT_FDCS;
  86.     else if (strneq(buf, "+FNS:", 5))
  87.         lastResponse = AT_FNSS;
  88.     else if (strneq(buf, "+FTI:", 5))
  89.         lastResponse = AT_FTSI;
  90.     else if (strneq(buf, "+FET:", 5))
  91.         lastResponse = AT_FET;
  92.     }
  93.     return (lastResponse);
  94. }
  95.  
  96. /*
  97.  * Abort a data transfer in progress.
  98.  */
  99. void
  100. Class20Modem::abortDataTransfer()
  101. {
  102.     char c = CAN;
  103.     putModemData(&c, 1);
  104. }
  105.  
  106. /*
  107.  * Send a page of data using the ``stream interface''.
  108.  */
  109. fxBool
  110. Class20Modem::sendPage(TIFF* tif)
  111. {
  112.     fxBool rc = TRUE;
  113.     protoTrace("SEND begin page");
  114.     if (flowControl == FLOW_XONXOFF)
  115.     setXONXOFF(FLOW_XONXOFF, FLOW_NONE, ACT_FLUSH);
  116.     /*
  117.      * Correct bit order of data if not what modem expects.
  118.      */
  119.     u_short fillorder;
  120.     TIFFGetFieldDefaulted(tif, TIFFTAG_FILLORDER, &fillorder);
  121.     const u_char* bitrev = TIFFGetBitRevTable(fillorder != conf.sendFillOrder);
  122.  
  123.     u_long* stripbytecount;
  124.     (void) TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &stripbytecount);
  125.     for (u_int strip = 0; strip < TIFFNumberOfStrips(tif) && rc; strip++) {
  126.     u_int totbytes = (u_int) stripbytecount[strip];
  127.     if (totbytes > 0) {
  128.         u_char* data = new u_char[totbytes];
  129.         if (TIFFReadRawStrip(tif, strip, data, totbytes) >= 0) {
  130.         /*
  131.          * Pass data to modem, filtering DLE's and
  132.          * being careful not to get hung up.
  133.          */
  134.         beginTimedTransfer();
  135.         rc = putModemDLEData(data, totbytes, bitrev, getDataTimeout());
  136.         endTimedTransfer();
  137.         protoTrace("SENT %d bytes of data", totbytes);
  138.         }
  139.         delete data;
  140.     }
  141.     }
  142.     if (!rc)
  143.     abortDataTransfer();
  144.     if (flowControl == FLOW_XONXOFF)
  145.     setXONXOFF(FLOW_CURRENT, FLOW_XONXOFF, ACT_DRAIN);
  146.     protoTrace("SEND end page");
  147.     return (rc);
  148. }
  149.  
  150. /*
  151.  * Handle the page-end protocol.
  152.  */
  153. fxBool
  154. Class20Modem::pageDone(u_int ppm, u_int& ppr)
  155. {
  156.     static char ppmCodes[3] = { 0x2C, 0x3B, 0x2E };
  157.     char eop[2];
  158.     fxBool seenHangup = FALSE;
  159.  
  160.     eop[0] = DLE;
  161.     eop[1] = ppmCodes[ppm];
  162.  
  163.     ppr = 0;                    // something invalid
  164.     if (putModemData(eop, sizeof (eop))) {
  165.     for (;;) {
  166.         switch (atResponse(rbuf, conf.pageDoneTimeout)) {
  167.         case AT_OK:                // page data good
  168.         case AT_ERROR:            // page data bad
  169.         if (seenHangup) {
  170.             /*
  171.              * Cannot query modem for post-page
  172.              * response after hangup, so simulate
  173.              * it here.
  174.              */
  175.             ppr = PPR_MCF;
  176.         } else {
  177.             fxStr ps;
  178.             if (atQuery("+FPS?", ps, 500))
  179.             ppr = atoi(ps);
  180.         }
  181.         return (TRUE);
  182.         case AT_FHNG:
  183.         if (!isNormalHangup())
  184.             return (FALSE);
  185.         seenHangup = TRUE;
  186.         break;
  187.         case AT_EMPTYLINE:
  188.         case AT_TIMEOUT:
  189.         case AT_NOCARRIER:
  190.         case AT_NODIALTONE:
  191.         case AT_NOANSWER:
  192.         goto bad;
  193.         }
  194.     }
  195.     }
  196. bad:
  197.     processHangup("50");            // Unspecified Phase D error
  198.     return (FALSE);
  199. }
  200.  
  201. /*
  202.  * Receive DLE-escaped data from the modem.
  203.  */
  204. fxBool
  205. Class20Modem::recvPageDLEData(TIFF* tif)
  206. {
  207.     fxBool prematureEOF = FALSE;
  208.     u_char buf[16*1024];
  209.     int n = 0;
  210.     for (;;) {
  211.     int b = getModemDataChar();
  212.     if (b == EOF) {
  213.         protoTrace("RECV: premature EOF");
  214.         prematureEOF = TRUE;
  215.         break;
  216.     }
  217.     if (b == DLE) {
  218.         b = getModemDataChar();
  219.         if (b == EOF || b == ETX) {
  220.         if (b == EOF) {
  221.             prematureEOF = TRUE;
  222.             protoTrace("RECV: premature EOF");
  223.         }
  224.         break;
  225.         }
  226.         if (b != DLE) {
  227.         if (n == sizeof (buf))
  228.             recvData(tif, buf, sizeof (buf)), n = 0;
  229.         buf[n++] = DLE;
  230.         // Class 2.0 requires <DLE><SUB> be converted to <DLE><DLE>
  231.         if (b == SUB)
  232.             b = DLE;
  233.         }
  234.     }
  235.     if (n == sizeof (buf))
  236.         recvData(tif, buf, sizeof (buf)), n = 0;
  237.     buf[n++] = b;
  238.     }
  239.     if (n > 0)
  240.     recvData(tif, buf, n);
  241.     return (prematureEOF);
  242. }
  243.